/*
 * @Author: “ygnnli” “1585923072@qq.com”
 * @Date: 2024-08-01 13:07:01
 * @LastEditors: “ygnnli” “1585923072@qq.com”
 * @LastEditTime: 2024-08-01 17:01:56
 * @FilePath: /110/38/Thread.cc
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <iostream>
#include <vector>
#include "Thread.hpp"
#include <unistd.h>
#include <vector>
// #include "LockGuard.hpp"

#include <mutex>

using namespace ThreadModoule;

// 数据不一致
int g_tickets = 10000; // 共享资源，没有保护的, 临界资源

class threadData
{
public:
    threadData(int &tickets, const std::string name, std::mutex &mutex)
        : _tickets(tickets), _name(name), _total(0), _mutex(mutex)
    {
    }

    ~threadData() {}

public:
    int &_tickets; // 所有的线程，最后都会引用同一个全局的g_tickets
    std::string _name;
    int _total;
    // pthread_mutex_t &_mutex;
    std::mutex &_mutex;
};

// pthread_mutex_t gmutex = PTHREAD_MUTEX_INITIALIZER;

// void route(threadData *td) // 抢票
// {
//     while (true)
//     {
// 访问临界资源的代码，叫做临界区！--- 我们加锁，本质就是把并行执行 --- 串行执行 --- 加锁的粒度要约细越好
//         // 1.  加锁 : 竞争锁是自由竞争的，竞争锁的能力太强的线程，会导致其他线程抢不到锁 --- 造成了其他线程的饥饿问题！
//         // pthread_mutex_lock(&gmutex);
//         pthread_mutex_lock(&td->_mutex);
//         if (td->_tickets > 0)
//         {
//             usleep(1000);
//             printf("%s running get tickets: %d\n", td->_name.c_str(), td->_tickets);
//             td->_tickets--;
//             pthread_mutex_unlock(&td->_mutex);// 解锁
//             td->_total++;
//         }
//         else
//         {
//             pthread_mutex_unlock(&td->_mutex);// 解锁
//             break;
//         }
//     }
// }

void route(threadData *td) // 抢票
{
    while (true)
    {
        // LockGuard guard(&td->_mutex);// 临时对象， RAII风格的加锁和解锁
        // td->_mutex.lock();
        std::lock_guard<std::mutex> lock(td->_mutex);
        if (td->_tickets > 0)
        {
            usleep(1000);
            printf("%s running get tickets: %d\n", td->_name.c_str(), td->_tickets);
            td->_tickets--;
            td->_total++;
            // td->_mutex.unlock();
        }
        else
        {
            // td->_mutex.unlock();
            break;
        }
    }
}

int main()
{
    // pthread_mutex_t mutex;
    // pthread_mutex_init(&mutex, NULL);

    std::mutex mutex;

    std::vector<Thread<threadData *>> threads;
    std::vector<threadData *> datas;
    // 1. 创建一批线程
    for (int i = 0; i < 5; i++)
    {
        std::string name = "thread-" + std::to_string(i + 1);
        threadData *td = new threadData(g_tickets, name, mutex);
        threads.emplace_back(route, td, name); // 任务  数值 名字
        datas.emplace_back(td);
    }

    // 2. 启动 一批线程
    for (auto &thread : threads)
    {
        thread.Start();
    }

    // 3. 等待一批线程
    for (auto &thread : threads)
    {
        thread.Join();
        // std::cout << "wait thread done, thread is: " << thread.name() << std::endl;
    }

    for (auto &data : datas)
    {
        std::cout << "thread: " << data->_name << " total: " << data->_total << std::endl;
        delete data;
    }

    // pthread_mutex_destroy(&mutex);

    return 0;
}